查看原文
其他

爬虫俱乐部助你回家—12306余票监测(二)

爬虫俱乐部 Stata and Python数据分析 2022-03-15

本文作者:杨长青

本文编辑:胡   婧

技术总编:张学人

有问题,不要怕!访问 

http://www.wuhanstring.com/uploads/5_aboutus/爬虫俱乐部-用户问题登记表.docx (复制到浏览器中)下载爬虫俱乐部用户问题登记表并按要求填写后发送至邮箱statatraining@163.com,我们会及时为您解答哟~

爬虫俱乐部的github主站正式上线了!我们的网站地址是:https://stata-club.github.io,粉丝们可以通过该网站访问过去的推文哟~

爬虫俱乐部隆重推出数据定制及处理业务,您有任何网页数据获取及处理方面的难题,请发邮件至我们邮箱statatraining@163.com,届时会有俱乐部高级会员为您排忧解难!

前情回顾

上一篇推文爬虫俱乐部助你回家—12306余票监测(一)主要介绍了如何爬取12306余票信息,并将余票信息导入到dataframe中。同时将代码封装到函数中,可以改变出发城市、目的城市以及出发日期。

本篇将解决上一篇推文尚未处理的问题,介绍如何将dataframe的内容提炼成文本,以及定时爬取12306余票信息,并微信发余票提醒

我们希望可以直接知道哪个车次有票,还剩几张票,剩余车票类型是什么。而不是在dataframe中花费时间去寻找信息。下面还是以1月26号徐州到滕州的火车票为例,介绍如何将dataframe的内容提炼成文本信息。

首先,将车票信息“无”替换成空,然后保留坐席不全为空的车次信息,程序如下:

df=get_news('徐州','滕州','2019-01-26') #调用上面的函数
df1=df.replace("无","") #将观测值为“无”的替换成空
df2=df1[(df1.商务座!="") | (df1.一等座!="")   | (df1.二等座!="")           |(df1.高级软卧!="")   |(df1.动卧!="")   |(df1.硬卧!="")             | (df1.软座!="")      |(df1.硬座!="")   | (df1.无座!="")  ].reset_index(drop=True) #最终只保留不是空的一条观测,即有票的车次信息

结果如下图所示,数据中所有“无”被删除,有16车次没有余票,被剔除。

接下来,对经过处理的数据进行提炼描述。如果经过上述处理的数据为空,则说明无票,输出“所有线路都没票了,步行吧~~”。否则证明还有有余票的车次,我们判断有余票的座次类别并输出余票张数。

程序如下:

#定义一个字典,键名是最终dataframe的列数,键值是列名
dict={   5: '商务座', 6: '一等座', 7: '二等座', 8: '高级软卧',9: '软卧',        
       10: '动卧',  11: '硬卧',  12: '软座',  13: '硬座',  14: '无座'}
if len(df2)==0:    news="所有线路都没票了,步行吧~~"  #如果一条观测都没有。说明当天所有车次都没有票
else:   #如果有票,则将车票信息和余票信息赋给字符串news    news="不慌不慌还有票"        for i in range(0,len(df2)):        news=news+"\n"+"车次为:"+df2.ix[i,0]+"\n"+"出发时间为: "+df2.ix[i,3]+"\n"+"到达时间为: "+df2.ix[i,4]+"\n"        for j in range(5,15):            
           if df2.ix[i,j]!="":                news=news+dict[j]+" :"+df2.ix[i,j]+'\n'
   print(news)

最终输出结果:

类似上篇封装函数的方法,我们也可以将上述dataframe信息处理提炼的过程封装成一个函数 send_news (start,end,day)。返回值是提炼后的文本。参数定义和get_news()相同。

定义程序如下:

def send_news(start,end,day):    df=get_news(start.title(),end.title(),day.title())    df1=df.replace("无","")    df2=df1[(df1.商务座!="") | (df1.一等座!="")   | (df1.二等座!="")           |(df1.高级软卧!="")   |(df1.动卧!="")   |(df1.硬卧!="")             | (df1.软座!="")      |(df1.硬座!="")   | (df1.无座!="")  ].reset_index(drop=True)# #保留有做的席位并重置索引    dict={   5: '商务座', 6: '一等座', 7: '二等座', 8: '高级软卧',9: '软卧',        
           10: '动卧',  11: '硬卧',  12: '软座',  13: '硬座',  14: '无座'}    
   if len(df2)==0:         news="所有线路都没票了,步行吧~~"  #如果一条观测都没有。说明当天所有车次都没有票    else:   ##如果有票,则将车票信息和余票信息赋给字符串news        news="不慌不慌还有票"            for i in range(0,len(df2)):            news=news+"\n"+"车次为:"+df2.ix[i,0]+"\n"+"出发时间为: "+df2.ix[i,3]+"\n"+"到达时间为: "+df2.ix[i,4]+"\n"            for j in range(5,15):                
               if df2.ix[i,j]!="":                    news=news+dict[j]+" :"+df2.ix[i,j]+'\n'    return news

现在我们尝试调用程序,查看武汉到滕州,1月26号车票信息。

send_news('武汉','滕州','2019-01-26')

最终输出结果如下:

小编打开高德地图,看到路线图,感觉还是放弃吧~~

爬虫俱乐部是您身边的科研助手,能够为您在数据处理实证研究中提供帮助。承蒙近四万粉丝的支持与厚爱,我们在腾讯课堂推出了网络视频课程,专注于数据整理、网络爬虫、循环命令编制和结果输出…李老师及团队精彩地讲解,深入浅出,注重案例与实战,让您更加快速高效地掌握Stata技巧及数据处理的精髓,而且可以无限次重复观看,在原有课程基础上已上传了三节全新的内容!百分百好评,简单易学,一个月让您从入门到精通。绝对物超所值!观看学习网址:

https://ke.qq.com/course/286526?tuin=1b60b462,

敬请关注!

由于12306火车票余票信息是动态的,可能会有人改签或者退票,有很大几率会刷出新票。所以可以连续抓取12306余票信息,进行余票监测,一旦有票则立即发送微信消息,进行抢票。这样就需要解决如下三个问题:

1

如何调用微信发送消息

2

判断是否有票,有票则发送微信消息,无票不需要提醒。

3

如何间隔一时间爬取一次12306余票信息,并运行上述程序。

我们一一解决上述问题,调用微信发送消息用到了我们前面提到的wxpy库,它可以实现微信登录、信息发送以及运行微信机器人(聊天机器人,自动加好友,自动管理群等)。我们这里用到的只是简单的微信发送消息。

程序如下,Bot指登录网页微信,我们这里可以用自己的小号或者朋友的微信登录,send_msg(news)指发送微信消息,“news”指代发送内容。在bot.friends().search('***')[0]***的位置更改成自己的微信号,或者在好友微信号中的备注。

#定义发送微信消息
bot=Bot()#登录微信号
def send_msg(news):      try:        
       # 添加朋友微信昵称        friend = bot.friends().search('长青')[0] #要发送人的微信昵称或备注信息        friend.send(news.title())    
   except:pass

下面我们来尝试将上文定义的函数send_news(start,end,day)返回的信息发送到微信上。

程序如下:

send_msg(send_news('武汉','滕州','2019-01-26'))

最终微信上收到了一条消息:

然后我们来解决第二个问题,判断是否有票,有票则发送微信消息,无票不需要提醒。这里和上面定义的send_news()函数类似,只续将return改成执行send_msg()函数即可。具体程序可参考上文send_news()函数定义,具体代码我们将在附件里给出。

由上面输出结果可以知道,武汉到滕州没有票,而徐州到滕州很多张票。现在分别运行以下程序,测试函数是否真的起作用。

w_news('徐州','滕州','2019-01-26') w_news('武汉','滕州','2019-01-26')

最终,第一条命令,发送了一条微信到微信号上:

第二条命令,仅仅在命令窗口打印“还是没有票,放弃吧~~”,而不会发送微信消息。

现在,还剩最后一个问题,即如何定时爬取余票信息并将处理好的信息,发送到微信号,提醒咱们抢票。这里就用到了前面提到的标准库time模块。

程序如下:

bot=Bot() #扫码登录微信号,前面扫过就不需要再运行
for i in range(1,100000):    w_news('徐州','滕州','2019-01-26') #参数可改    print('第%d次执行\n'%i)    time.sleep(30) #以秒为单位,可以更改时间间隔

最终可以程序一直在执行,一旦有票,立即发送微信消息,由于徐州到滕州有票,所以会一直在发送消息。

现在小编就把函数参数改成“武汉”,“滕州”,“2018-01-26”,因为暂时没有车票,所以不会发送微信,只会在命令窗口显示:

现在,小编在默默的等待着微信消息了,你呢?快些行动起来吧!最后祝愿所有思乡的人儿,都能顺顺利利回家团圆!

完整代码我们将其上传到了爬虫俱乐部的腾讯云里:

https://stata-club-1257787903.cos.ap-chengdu.myqcloud.com/code.py

对爬虫俱乐部的推文累计打赏超过1000元我们即可给您开具发票,发票类别为“咨询费”。用心做事,只为做您更贴心的小爬虫!

往期推文推荐


关于我们

微信公众号“爬虫俱乐部”分享实用的stata命令,欢迎转载、打赏。爬虫俱乐部是由李春涛教授领导下的研究生及本科生组成的大数据分析和数据挖掘团队。



此外,欢迎大家踊跃投稿,介绍一些关于stata的数据处理和分析技巧。

投稿邮箱:statatraining@163.com

投稿要求:
1)必须原创,禁止抄袭;
2)必须准确,详细,有例子,有截图;
注意事项:
1)所有投稿都会经过本公众号运营团队成员的审核,审核通过才可录用,一经录用,会在该推文里为作者署名,并有赏金分成。
2)邮件请注明投稿,邮件名称为“投稿+推文名称”。
3)应广大读者要求,现开通有偿问答服务,如果大家遇到关于stata分析数据的问题,可以在公众号中提出,只需支付少量赏金,我们会在后期的推文里给予解答。


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存